home *** CD-ROM | disk | FTP | other *** search
/ Java Developer's Companion / Java Developer's Companion.iso / Javacup / EDUHM01H.TAR / education / EDUHM01H / Turing.java < prev    next >
Text File  |  1996-05-21  |  27KB  |  992 lines

  1. /* This applet simulates the working of a Turing Machine. Users can */
  2. /* run ready-made files or write their own programs.                */
  3. /* March 25 1996                                                    */
  4. /* Buena Vista University JAVA Team under direction of              */
  5. /* Ken Schweller         schweller@bvu.edu                          */
  6.  
  7.  
  8. import java.lang.*;
  9. import java.io.*;
  10. import java.awt.*;
  11. import java.net.*;
  12. import java.applet.*;
  13. import java.util.*;
  14.  
  15. public class Turing extends Applet implements Runnable {
  16.    int direction;
  17.    Thread MachineThread;
  18.    int sleep_delay;
  19.    int start = 80;
  20.    int shift = 0;
  21.    boolean illegalsymbol;
  22.    Image im;
  23.    Image Turingpic;
  24.    Graphics pic;
  25.    Color bgcolor;
  26.    AudioClip loada;
  27.    AudioClip flusha;
  28.    AudioClip stepa;
  29.    AudioClip errora;
  30.    AudioClip talka;
  31.    AudioClip pressa;
  32.    AudioClip reela;
  33.    AudioClip fasta;
  34.    AudioClip overa;
  35.    AudioClip picta;
  36.    URL url;
  37.    int state;
  38.    Font picfont;
  39.    Font Tfont;
  40.    Font Tbigfont;
  41.    Font Tbiggerfont;
  42.    Font Tbigbigfont;
  43.    Font statefont;
  44.    Font Mfont;
  45.    Font bfont;
  46.    char action;
  47.    boolean done;
  48.    boolean alldone;   
  49.    boolean running;
  50.    int qt = 0;
  51.    int ds[][] = new int[25][37];
  52.    char da[][] = new char[25][37];
  53.    boolean eyebrows_up;
  54.    TextField StateField;
  55.    int rot = 1;
  56.    String m1;
  57.    String message1;
  58.    String message2;
  59.    String message3;
  60.    char tape[] = new char[1000];;
  61.    char ptape[] = new char[1000];
  62.    int ptr,cs,insertpt;
  63.    int cstate;
  64.    int move_s;
  65.    char move_a;
  66.    int r;
  67.    String  at;
  68.    String filename;
  69.    String line;
  70.    String legalsymbols;
  71.    TextArea rules;
  72.    char l1,l2,x,symb;
  73.    int q,j,l,s1,s2;
  74.    boolean compute_pressed; 
  75.    boolean auto_pressed;
  76.    boolean reel_pressed;
  77.    char symbol[]= new char[37];
  78.    int sp;
  79.    Choice opt;
  80.    int lastrn;
  81.    String quote[][] = 
  82. {{"I believe that a Turing Machine",
  83.   "can carry out any computation",
  84.   "that any computer can!"},
  85.  {"Have you tried to program your",
  86.   "own tape for this machine? It's",
  87.   "not too hard to do. Try it!"},
  88.  {"During WW2 I worked in British",
  89.   "Intelligence trying to crack the",
  90.   "German Enigma code..."},
  91.  {"Did you know that I was a long",
  92.   "distance runner and also an",
  93.   "expert chess player?"},
  94.  {"I believe that by the end of the century",
  95.   "one will be able to speak of machines thinking",
  96.   "without expecting to be contradicted..."},
  97.  {"In 1950 I wrote an article called 'Computing Machinery",
  98.   "and Intelligence' in which I tried to answer the",
  99.   "question: Can Machines Think?"},
  100.  {"I once proposed we test whether machines can think",
  101.   "by seeing whether a blindfolded interrogator could",
  102.   "discriminate between the answers of a man and a machine."}
  103. };
  104.  
  105. String sillyquote[] = {"Hey, that tickles!",
  106.                        "Uh, Having fun with my Machine?",
  107.                        "Ha ha.. getting tired of operating the Machine?",
  108.                        "I see you like to click on things.. try the Tape Rollers!"};
  109. int lastsillyrn = 3;
  110. int hix[] = new int[5];  // position of high smoke clouds
  111. int hiy[] = new int[5];
  112. int hicn = -1;
  113. int badentry = 0;
  114. boolean badsymbol = false;
  115.  
  116. boolean  isvalid(int m, char a) {
  117. // check whether suggested move is valid
  118.    if (m == -999 || a ==0 ){
  119.         return(false);
  120.    }
  121.    else 
  122.      return(true);
  123. }
  124.  
  125. int convert(char p){
  126. // convert symbol typed in to legal symbol
  127.   int v= -999;
  128.   if (p>64 && p < 91)
  129.      v = p - 55;
  130.   if (p>47 && p<58)
  131.      v = p - 48;
  132.   if (p== '-' || p==' ')
  133.      v = 32;
  134.    return(v);
  135. }
  136.  
  137. void cleartape()
  138. // erase symbols on inputoutput tape
  139. {
  140.    int i;
  141.    for(i=0;i<1000;i++){
  142.       tape[i]=' ';
  143.       ptape[i]=' ';
  144.    }
  145. }
  146.  
  147. void updatebuffer(){
  148. // enter rules in rule list into state-symbol table
  149.     for (q=0; q<25; q++)        /* init transition states to -999 */
  150.       for (l=0; l<37; l++){
  151.           ds[q][l]= -999;
  152.           da[q][1]= '#';
  153.       } 
  154.    for (q = 0; q<37; q++)
  155.      symbol[q] = '#';
  156.    String line;
  157.    sp = -1;
  158.    String lstring;
  159.    boolean badline = false;
  160.    String buffer = rules.getText().toUpperCase();
  161.    String delim = "\n";
  162.    StringTokenizer r = new StringTokenizer(buffer,delim);
  163.    int linenum = 1;
  164.    while (r.hasMoreTokens() && !badline){
  165.      line = r.nextToken();
  166.      // parse the line into the transition matrix
  167.       StringTokenizer t = new StringTokenizer(line);
  168.       try{
  169.           s1 = Integer.valueOf(t.nextToken()).intValue();
  170.           if (s1 < 0 || s1 >36){
  171.              badline = true;
  172.              eyebrows_up = true;
  173.              message1 = "Loading Error in Rule #"+linenum;
  174.              message2 = "State number must be between 0 and 36.";
  175.           }
  176.           lstring = t.nextToken();
  177.           if (lstring.length()>1){
  178.              badline = true;
  179.              eyebrows_up = true;
  180.              message1 = "Loading Error in Rule #"+linenum;
  181.              message2 = "Symbol must be a single character.";
  182.           }else l1 = lstring.charAt(0);
  183.           if (convert(l1)==-999){
  184.              badline = true;
  185.              eyebrows_up = true;
  186.              message1 = "Loading Error in Rule #"+linenum;
  187.              message2 = "Symbol must be a letter,digit, or space";
  188.           }
  189.           s2 = Integer.valueOf(t.nextToken()).intValue();
  190.           if (s2 < 0 || s2 >36){
  191.              badline = true;
  192.              eyebrows_up = true;
  193.              message1 = "Loading Error in Rule #"+linenum;
  194.              message2 = "State number must be between 0 and 36.";
  195.           }
  196.  
  197.           lstring = t.nextToken();
  198.           if (lstring.length()>1){
  199.              badline = true;
  200.              eyebrows_up = true;
  201.              message1 = "Loading Error in Rule #"+linenum;
  202.              message2 = "Symbol must be a single character.";
  203.           }else l2 = lstring.charAt(0);
  204.           if (convert(l2)==-999 && (l2 != '<') && (l2 != '>')){
  205.              badline = true;
  206.              eyebrows_up = true;
  207.              message1 = "Loading Error in Rule #"+linenum;
  208.              message2 = "Symbol must be a letter,digit, -, <, or >";
  209.           }
  210.           }
  211.       catch (java.util.NoSuchElementException e)
  212.          {message2 = "Warning: Rule "+linenum+" is malformed...";
  213.              eyebrows_up = true;
  214.           badline = true;
  215.          }
  216.       catch (java.lang.NumberFormatException e)
  217.          { message1 = "Loading Error in Rule #"+linenum;
  218.            message2 = "State must be a number between 0 and 36.";
  219.              eyebrows_up = true;
  220.            badline = true;
  221.          }
  222.       if (t.hasMoreTokens())
  223.         { message1 = "Warning: Possible Error in Rule #"+linenum;
  224.          message2 = "Rule seems to have too many entries...";
  225.              eyebrows_up = true;
  226.       }
  227.       if (!badline){
  228.       store_symbol(l1);
  229.       if (l2 != '<' && l2 != '>'  )
  230.            store_symbol(l2);
  231.       ds[s1][convert(l1)] = s2;
  232.       da[s1][convert(l1)] = l2;
  233.  
  234.        linenum++;
  235.      }
  236.    }
  237.    rules.selectAll();
  238.    rules.replaceText(buffer,0,rules.getSelectionEnd());
  239. }
  240.  
  241.  
  242. void clear_messages(){
  243.   message1="";
  244.   message2="";
  245.   message3="";
  246. }
  247.  
  248. void loadfile(String filename){
  249. // load selected program file
  250.    boolean no_errors = true;
  251.    cleartape();
  252.    ptr = 500;
  253.    cs = 0;
  254.    clear_messages();
  255.    s2 = 0;
  256.    s1 = 0;
  257.    l2 = '>';
  258.    l1 = '<';
  259.    rules.selectAll();
  260.    rules.replaceText("",0,rules.getSelectionEnd());
  261.    message1 = "Opening File: "+filename;
  262.    //Attempt to Open File   
  263.    DataInputStream file = null;
  264.    try 
  265.    {  
  266.      url = new URL(getDocumentBase(), filename);
  267.      file = new DataInputStream(url.openStream());        
  268.      line = file.readLine().trim();
  269.    }   
  270.    catch (java.net.MalformedURLException e)
  271.    {
  272.      message2 = "Unable to open file: Unknown URL..";
  273.      errora.play();
  274.      no_errors = false;
  275.    }
  276.    catch (java.io.IOException e)
  277.    {
  278.      message2 = "Unable to open file: "+filename;
  279.      errora.play();
  280.      no_errors = false;
  281.    }
  282.    catch(java.lang.NullPointerException e)
  283.    {
  284.      message2 = "Unable to read file: "+filename;
  285.      errora.play();
  286.      no_errors = false;
  287.    }
  288.    //read data from file
  289.    if (no_errors){
  290.       while ((line.charAt(0)=='#') && no_errors){
  291.         message2 = message3;
  292.         message3 = line;
  293.         try 
  294.           {
  295.             line = file.readLine().trim();
  296.           }
  297.           catch(java.io.IOException e)
  298.           {
  299.             message2 = "Unable to read line..";
  300.             errora.play();
  301.             no_errors = false;
  302.           }
  303.        }
  304.        if (no_errors){
  305.          ptr = 500;                   /* load tape at position 500 */
  306.          x = 0;
  307.          while( x< line.length()){
  308.             tape[ptr++] = uppercase(line.charAt(x));
  309.             x++;
  310.          }
  311.          ptr = 500;       
  312.          try 
  313.            { 
  314.               line = file.readLine().trim();
  315.               q = Integer.valueOf(line).intValue();
  316.               for(j=1;j<=q;j++){   
  317.                 line = file.readLine().trim().toUpperCase();
  318.                 rules.insertText("\n",500);
  319.                 rules.insertText(line,500);
  320.               }
  321.            }
  322.            catch(java.io.IOException e)
  323.            {
  324.              message2 = "Unable to read line..";
  325.              errora.play();
  326.              no_errors = false;
  327.            }   
  328.        }
  329.        if (no_errors)
  330.           updatebuffer();
  331.    }
  332. }
  333.  
  334.  
  335.  
  336. public void init() {
  337.  
  338.    loada = getAudioClip(getCodeBase(),"load.au");
  339.    flusha = getAudioClip(getCodeBase(),"flush.au");
  340.    stepa  = getAudioClip(getCodeBase(),"step.au");
  341.    errora = getAudioClip(getCodeBase(),"error.au");
  342.    talka  = getAudioClip(getCodeBase(),"talk.au");
  343.    pressa = getAudioClip(getCodeBase(),"press.au");
  344.    reela = getAudioClip(getCodeBase(), "reel.au");
  345.    overa = getAudioClip(getCodeBase(), "over.au");
  346.    fasta = getAudioClip(getCodeBase(), "fast.au");
  347.    picta = getAudioClip(getCodeBase(), "stepbak.au");
  348.    
  349.    Tfont = new Font("Courier", Font.PLAIN, 12);
  350.    Tbigfont = new Font("Courier", Font.BOLD, 14);
  351.    Tbiggerfont = new Font("Courier", Font.BOLD, 18);
  352.    Tbigbigfont = new Font("Courier", Font.BOLD, 20);
  353.    picfont = new Font("Times", Font.BOLD, 9);
  354.    statefont = new Font("Times", Font.BOLD, 11);
  355.    Mfont = new Font("Times", Font.ITALIC, 14);
  356.    bfont = new Font("Courier", Font.PLAIN, 1);
  357.   
  358.    String at = getParameter("files");
  359.    StringTokenizer programs = new StringTokenizer(at);
  360.    im = createImage(size().width, size().height);
  361.    pic = im.getGraphics();
  362.    Turingpic =  getImage(getCodeBase(), "Turing_small.gif");
  363.    eyebrows_up = false;
  364.    overa.play();
  365.    bgcolor = new Color(66,111,66);
  366.    setLayout(new BorderLayout());
  367.    Panel sp = new Panel();
  368.    add("South",sp);
  369.    sp.add(new Button("Talk"));
  370.    sp.add(new Button("Clear"));
  371.    sp.add(new Button("Stop"));
  372.    sp.add(new Button("FastAuto"));
  373.    sp.add(new Button("Auto"));
  374.    opt = new Choice();
  375.    while( programs.hasMoreTokens())
  376.       opt.addItem(programs.nextToken());
  377.    sp.add(new Button("Step"));
  378.    sp.add(new Button("Change State"));
  379.    sp.add(StateField = new TextField("0",3));
  380.    sp.add(new Button("Load"));
  381.    sp.add(opt);
  382.    sp.add(new Button("Update"));
  383.    sp.setBackground(bgcolor);
  384.    Panel ep = new Panel();
  385.    ep.setFont(bfont);
  386.    ep.setBackground(bgcolor);
  387.    add("East", ep);
  388.    rules =  new TextArea(13,10);
  389.    ep.add(rules);
  390.    cleartape();
  391.    ptr = 500;
  392.    cs = 0;
  393.    done = false;
  394.    running = false; 
  395.    sleep_delay = 600;
  396.    message1 = "Welcome to the Turing Machine...";
  397.    message2 = "Please click on the screen to begin. You may"; 
  398.    message3 = "then load a program to run or write your own!";
  399.    lastrn = 1;
  400.    repaint();
  401.    this.requestFocus();
  402.    }
  403.  
  404.  
  405. void drawshadedString(String s, int x, int y, Graphics g){
  406. //  draw letters with a shadow
  407.   Color temp = g.getColor();
  408.   g.setColor(Color.black);
  409.   g.drawString(s, x+1,y+1);
  410.   g.setColor(temp);
  411.   g.drawString(s,x,y);
  412.  
  413. }
  414.  
  415.  
  416. void writeMessages(Graphics g){
  417.   drawshadedString(message1,65,35,g );
  418.   drawshadedString(message2,65,50,g);
  419.   drawshadedString(message3,65,65,g );
  420. }
  421.  
  422. boolean symbol_stored(char c){
  423. // see if symbol has already occurred in rules
  424.    int j = 0;
  425.    while (j<20 && symbol[j] != c)
  426.      j++;
  427.    if (j<20)
  428.       return true;
  429.    else
  430.       return false;
  431. }
  432.  
  433. void store_symbol(char c){
  434. // store the symbol as a valid rule list symbol
  435.    if (!symbol_stored(c)){
  436.      sp = sp + 1;
  437.      symbol[sp] = c; 
  438.    }
  439. }
  440.  
  441.  
  442. char uppercase(int key){
  443. // convert symbol to legal uppercase symbol
  444.    if (key > 96 && key < 123)
  445.       return (char)(key - 32);
  446.    else if (key == '-')
  447.       return ' ';
  448.    else
  449.       return (char)key;
  450. }
  451.  
  452.  
  453. public boolean mouseDown(java.awt.Event e, int x, int y){
  454.     clear_messages();
  455.     if (x>5 && x<52 && y>4 && y<70){
  456.       // if Turings picture is clicked
  457.       if (badsymbol){
  458.         // check validity of last typed in symbol
  459.         errora.play();
  460.         message1 = "Uh, I couldn't help noticing that your previous entry";
  461.         message2 = "of '"+(char)badentry+"' does not yet appear in any rule.."; 
  462.         badsymbol = false;
  463.       }
  464.       else if (rules.getText().length() == 0){
  465.          // rules list must be empty
  466.          picta.play();
  467.          message1 = "I notice that you haven't loaded in any files or written";
  468.          message2 = "your own rules yet.  Why not give it a try?";
  469.       }
  470.       else{
  471.         picta.play();
  472.         // return an informative Turing quote
  473.         get_silly_quote();
  474.       }
  475.     }
  476.     else if(y>167 && y<177)
  477.              // user has pressed a Tape Reel button
  478.              if (x>start-6 && x <start+9){
  479.                 reela.play();
  480.                 direction = '>';
  481.                 reel_pressed = true;
  482.              }
  483.           else if (x>start+354 && x < start+369){
  484.                     reela.play();
  485.                     direction = '<';
  486.                     reel_pressed = true;
  487.                    }
  488.     if (x>start+15 && x<start+348 && y>147 && y<161){
  489.        // user has clicked on the tape
  490.        talka.play();
  491.        message2 = "To change tape symbols just type in what you want..";
  492.     }
  493.     else if (x>start+165 && x<start+202 && y>85 && y<130){
  494.             // user has clicked on the Turing machine black box
  495.             eyebrows_up = true;
  496.             errora.play();
  497.  message1 = "I can't show you what's inside the box. The implementation";
  498.  message2 ="of the machine is not what's really important. My theory";
  499.  message3 ="is valid even if the machine is made of rubberbands and paper clips!";
  500.          } 
  501.     repaint();
  502.     return true;
  503. }
  504.  
  505. public boolean keyDown(java.awt.Event e, int key){
  506.     clear_messages();
  507.     if (e.target == this){
  508.       // User is trying to enter new symbols on tape
  509.       illegalsymbol = false;
  510.       if (convert(uppercase(key)) == -999){
  511.         message2 = "Illegal Symbol: Symbol must be a letter, space, or digit";
  512.         illegalsymbol = true;
  513.         eyebrows_up = true;
  514.         errora.play();
  515.         repaint();
  516.         return true;
  517.       }else{
  518.         if (!symbol_stored(uppercase(key)) && (key != 32)){
  519.              // user has entered an illegal symbol
  520.              eyebrows_up = true;
  521.              badentry = uppercase(key);
  522.              badsymbol = true;
  523.         }
  524.         // add symbol to tape
  525.         tape[ptr] = uppercase(key);
  526.         pressa.play();
  527.         repaint();
  528.         return true;}
  529.     }else {
  530.       return super.keyDown(e, key); 
  531.     }
  532. }
  533.  
  534. public boolean keyUp(java.awt.Event e, int key){
  535.    if (e.target == this){
  536.       if (!illegalsymbol){
  537.           direction = '>';
  538.           reel_pressed = true;
  539.           repaint();
  540.       }
  541.       return true;
  542.    }
  543.    else 
  544.       return super.keyUp(e, key);
  545. }
  546.  
  547. public boolean action(java.awt.Event evt,Object arg ){
  548. // A button has been pressed.. carry out action
  549.     String button= "";
  550.     running = true;
  551.     alldone = false;
  552.     done = false;
  553.     clear_messages();
  554.     this.requestFocus();
  555.     try { button = ((Button)evt.target).getLabel();}
  556.     catch(java.lang.ClassCastException e) {}
  557.     if (button == "Step"){
  558.        // make a single machine move
  559.        compute_pressed = true;
  560.        pressa.play();
  561.        repaint();
  562.     }
  563.     else if (button == "Auto"){
  564.        // continue making moves until halting
  565.        sleep_delay = 600;
  566.        auto_pressed = true;     
  567.     }
  568.     else if (button == "FastAuto"){
  569.        // Fast automatic
  570.        sleep_delay = 10;
  571.        auto_pressed = true;
  572.     }
  573.     else if (button == "Stop"){
  574.        // halt automatic running
  575.        auto_pressed = false;
  576.        errora.play();
  577.     }
  578.     else if (button == "Clear"){
  579.        // clear the tape
  580.        flusha.play();
  581.        cleartape();
  582.        repaint();
  583.     }
  584.     else if (button == "Update"){
  585.        // load rule list into State-Symbol table
  586.        message2 = "Updating the Rule List...";
  587.        loada.play();
  588.        updatebuffer();
  589.        repaint();
  590.     }
  591.     else if (button == "Load"){
  592.        // load a program file
  593.        loada.play();
  594.        loadfile(opt.getSelectedItem());
  595.        repaint();
  596.     }
  597.     else if (button == "Talk"){
  598.        // let Turing spout a random saying
  599.        talka.play();
  600.        get_quote();
  601.        repaint();
  602.     }
  603.     else if (button == "Change State"){
  604.        // Change the state of the machine
  605.        cs = Integer.valueOf(StateField.getText()).intValue();
  606.        loada.play();
  607.        repaint();
  608.     }
  609.     return true;           
  610. }
  611.  
  612. public void drawwhitesquares(Graphics g, int xpos, int ypos) {
  613. // draw white blank tape
  614.    g.setColor(Color.white);
  615.    g.fillRoundRect(xpos, ypos, 11, 18, 4, 4);
  616. }
  617.       
  618. public void drawBox(Graphics g, int xpos, int ypos) {
  619. // draw boxes on tape
  620.    g.setColor(Color.red);
  621.    g.drawRoundRect(xpos, ypos, 11, 18, 4, 4);
  622. }
  623.  
  624.  
  625.  
  626. public void draw_machine(int start, int x, int y, Graphics g){
  627. // draw complete Turing machaine from x start point
  628.   int xpt[] = new int[4];
  629.   int ypt[] = new int[4];
  630.   g.fill3DRect(x, y,50,50,true);
  631.   g.setColor(Color.black);
  632.   g.fill3DRect(start+175,145,13,20,true);
  633.   g.setColor(Color.white);
  634.   g.fillRect(start+177,147,9,16);
  635.      g.setFont(statefont);
  636.      drawshadedString("State", x+12,y+40,g);
  637.      g.setColor(Color.white);
  638.      g.fillRect(x+10,y+3,30,22);
  639.      g.setColor(Color.black);  
  640.      g.drawRect(x+10,y+3,30,22);
  641.      Integer state = new Integer(cs);
  642.      g.setFont(Tbigbigfont);
  643.      FontMetrics fm = g.getFontMetrics();
  644.      String statestring = state.toString();
  645.      int sswidth = fm.stringWidth(statestring); 
  646.      g.drawString(statestring,x+10+(30 - sswidth)/2 ,y+20);
  647.      g.setFont(Tbigfont);
  648.      StateField.setText(state.toString());
  649.   xpt[0] = x;
  650.   xpt[1] = x-20;
  651.   xpt[2] = x+30;
  652.   xpt[3] = x + 50;
  653.   ypt[0] = y;  
  654.   ypt[1] = y-20;
  655.   ypt[2] = y-20;
  656.   ypt[3] = y;
  657.   //draw top of box
  658.   g.setColor(Color.lightGray);
  659.   g.fillPolygon(xpt, ypt, 4);
  660.   xpt[2] = x-20;
  661.   xpt[3] = x;
  662.   ypt[2] = y+30;
  663.   ypt[3] = y+50;
  664.   //draw smoke stack
  665.   g.setColor(Color.black);
  666.   g.fillRect(x+20, y-25, 9,15);
  667.   g.fillOval(x+20,y-21,9,15);
  668.   g.setColor(Color.white);
  669.   g.fillOval(x+20, y-28,9,5);
  670.   //draw smoke 
  671.   g.setColor(Color.lightGray);
  672.   for(int k = 0; k<hicn;k++)
  673.     g.fillOval(hix[k], hiy[k],4,4);
  674.   int cn=(int)Math.floor(Math.random()*4); 
  675.   hicn = cn;
  676.   for(int j=0; j<cn; j++){
  677.     int cx = x + 15 +(int)Math.floor(Math.random()*15); 
  678.     int cy = y - 35 -(int)Math.floor(Math.random()*20); 
  679.     g.fillOval(cx,cy,6,6);
  680.     hix[j] = cx+6;
  681.     hiy[j] = cy-20;
  682.   }
  683.   g.setColor(Color.black);
  684.   g.fillPolygon(xpt, ypt, 4);
  685.   xpt[0] = x + 10;
  686.   xpt[1] = x + 24;
  687.   xpt[2] = start+185;
  688.   xpt[3] = start+177;
  689.   ypt[0] = y + 50;
  690.   ypt[1] = y + 50;
  691.   ypt[2] = 146;
  692.   ypt[3] = 146;
  693.   g.fillPolygon(xpt,ypt,4);
  694. }
  695.  
  696.  
  697. void draw_letters(int xstart, Graphics g){
  698. // draw letters on tape
  699.   int start = ptr-17;
  700.   int x = xstart-8;
  701.   boolean ok2draw;
  702.   g.setFont(Tfont);
  703.   for (int index = start; index < start + 35; index++){
  704.     ok2draw = true;
  705.     if (index == ptr){
  706.       g.setFont(Tbigfont);
  707.       g.drawChars(tape, index,1,x-1, 159);
  708.       g.setFont(Tfont);
  709.       ok2draw = false;
  710.     }
  711.     if (index == ptr+17){
  712.         ok2draw = false;
  713.         if (shift <=0)
  714.            g.drawChars(tape,index,1,x,157);
  715.         }
  716.     if (index == ptr-17){
  717.         ok2draw = false;
  718.         if (shift >= 0)
  719.            g.drawChars(tape, index, 1,x, 157);
  720.         }  
  721.     if (ok2draw)
  722.              g.drawChars(tape,index,1, x,159);
  723.     x = x + 11;
  724.   }
  725. }
  726.  
  727. void get_silly_quote(){
  728.     int n = (int)Math.floor(Math.random()*4);
  729.     while (n == lastsillyrn)
  730.       n = (int)Math.floor(Math.random()*4);
  731.     lastsillyrn = n;
  732.     clear_messages();
  733.     message2 = sillyquote[n];
  734. }
  735.  
  736. void get_quote(){
  737. // get informative quote
  738.     int n = (int)Math.floor(Math.random()*7);
  739.     while (n == lastrn)
  740.       n = (int)Math.floor(Math.random()*7);
  741.     lastrn = n;
  742.     message1 = quote[n][0];
  743.     message2 = quote[n][1];
  744.     message3 = quote[n][2];
  745. }
  746.  
  747.  
  748. void draw_spokes(int start, Graphics g){
  749. // draw spokes in tape reel
  750.    int spoke[][]  = {{0,-4},{12,0},{0,+4},{-12,0}};
  751.    if (rot>3) rot = 0;
  752.    if (rot<0)  rot = 3;
  753.    g.setColor(Color.black);
  754.    g.drawLine(start+2,131, start+2+spoke[rot][0], 131+spoke[rot][1]);
  755.    g.drawLine(start+362,131, start+362+spoke[rot][0], 131+spoke[rot][1]);
  756. }
  757.  
  758. void draw_reels(int start,Graphics g){
  759.     g.setColor(Color.black);
  760.     g.fillRect(start-11,130,25,50);
  761.     g.fillRect(start+349,130,25,50);
  762.     g.fillOval(start-11,176,25,9);
  763.     g.fillOval(start+349,176,25,9);
  764.     g.setColor(Color.white);
  765.     int xb[] = {start-6,start+9,start+9};
  766.     int yb[] = {172,167,177};
  767.     g.fillPolygon(xb,yb,3);
  768.     xb[0] = start+369;
  769.     xb[1] = start+354;
  770.     xb[2] = start+354;
  771.     g.fillPolygon(xb,yb,3);
  772.     int xpt[]= {start-11,start+shift,start+shift,start-11};
  773.     int ypt[]= {142,145,163,160};
  774.     g.fillPolygon(xpt, ypt, 4);
  775.     g.setColor(Color.red);
  776.     g.drawPolygon(xpt,ypt,4);
  777.     g.setColor(Color.white);
  778.     xpt[0] = start+shift+363;
  779.     xpt[1]=start+374;
  780.     xpt[2]=start+374;
  781.     xpt[3]=start+shift+363;
  782.     ypt[0] = 145;
  783.     ypt[1] = 142;
  784.     ypt[2] =  160;
  785.     ypt[3] =  163;
  786.     g.fillPolygon(xpt,ypt,4);
  787.     g.setColor(Color.red);
  788.     g.drawPolygon(xpt,ypt,4);
  789.     g.setColor(Color.white);
  790.     g.fillOval(start-11,126,25,9);
  791.     g.fillOval(start+349,126,25,9); 
  792.     draw_spokes(start,g);
  793. }
  794.  
  795. public void paintPIC(Graphics g){
  796. // offscreen graphic
  797.      Dimension r = size();
  798.      g.clearRect(0,0,r.width, r.height);
  799.      g.setColor(bgcolor);
  800.      g.fillRect(0,0,r.width, r.height);
  801.      draw_reels(start,g);
  802.      // draw the tape
  803.      for(int i=start+shift; i<start+shift+363; i+=11)
  804.         drawwhitesquares(g,i,145);
  805.      for(int i=start+shift; i<start+shift+363; i+=11)
  806.         drawBox(g,i,145);
  807.      g.setColor(Color.red);
  808.      int boxx  = start+163 +(int)Math.floor(Math.random()*8); 
  809.      int boxy  = 83 +(int)Math.floor(Math.random()*10); 
  810.      // draw rest of machine
  811.      draw_machine(start,boxx, boxy, g);
  812.      g.setColor(Color.black);
  813.      draw_letters(start+shift,g);
  814.      g.setColor(Color.black);
  815.      g.setFont(statefont);
  816.      // add picture of Turing
  817.      g.drawRect(4,4,50,60);
  818.      g.drawString("Alan Turing",5,88);
  819.      g.drawString("1912 - 1954",5,100); 
  820.      g.fillRect(2,2,56,73);
  821.      g.drawImage(Turingpic, 10, 5, this);
  822.      if (eyebrows_up){
  823.         g.drawLine(38,24,44,27);
  824.         g.drawLine(46,27,49,24);
  825.         eyebrows_up = false;
  826.      }
  827.      // see if done
  828.      if (done) {
  829.          g.setColor(Color.red);
  830.          message1 ="Computation HALTED...";
  831.          if (!symbol_stored(uppercase(tape[ptr])) && (tape[ptr] != 32)){
  832.            message2 = "  Unrecognized symbol on tape...";
  833.            errora.play();
  834.          }
  835.          else{
  836.            message2 = " I think we might be done because";
  837.            message3 = "   I have no rule for this situation..."; 
  838.            overa.play();
  839.          }
  840.          alldone = true;
  841.          done = false; 
  842.      }
  843.      // add messages and labels
  844.      g.setFont(statefont);
  845.      g.setColor(Color.yellow);
  846.      writeMessages(g);
  847.      g.setColor(Color.black);
  848.      g.setFont(Tbiggerfont);
  849.      g.setColor(Color.red);
  850.      drawshadedString("Ye Olde Turing Machine",160,19,g);
  851.      g.setFont(statefont);
  852.      g.setColor(Color.white);
  853.      drawshadedString("Input/Output Tape",start+50, 180,g);
  854.      drawshadedString("<= Turing Machine", start+222, 110,g);
  855.      drawshadedString("Rule List =>", r.width-175,80,g);
  856. }
  857.  
  858. public void paint(Graphics g) {
  859. // paint to screen
  860.       paintPIC(pic);
  861.       g.drawImage(im,0,0,null);
  862. }
  863.  
  864.  
  865. public void start(){
  866. // new thread for automatic running of machine
  867.   MachineThread = new Thread(this);
  868.   MachineThread.start();
  869.   requestFocus();
  870. }
  871.  
  872. public void run(){
  873. // run machine as long as auto_pressed is on
  874.    int timer = 0;
  875.    while (MachineThread != null) {
  876.      try {Thread.sleep(sleep_delay);}
  877.      catch(InterruptedException e) {}
  878.      if (auto_pressed){
  879.          if (timer++%100 == 0){
  880.             fasta.play();
  881.          }
  882.          compute_pressed=true;
  883.          repaint();
  884.      }
  885.    }
  886.    repaint();
  887. }
  888.  
  889.  
  890. public void update(Graphics g){   
  891. if (reel_pressed){
  892.   // advance or retract tape
  893.   switch(direction) {
  894.                case '>':
  895.                      rot++;
  896.                      shift = -5;
  897.                      paint(g);
  898.                      rot++;
  899.                      ptr++;
  900.                      shift = 0;
  901.                      break;
  902.                case '<':
  903.                      rot--;
  904.                      shift = 5;
  905.                      paint(g);
  906.                      rot--;
  907.                      ptr--;
  908.                      shift = 0;
  909.                      break;
  910.    } 
  911.  paint(g);
  912.  reel_pressed = false;
  913. }else
  914.  if (shift==0){
  915.    // calculate new move
  916.    if (running && compute_pressed){
  917.        int ts = convert(tape[ptr]);
  918.        if (ts != -999){
  919.        move_s = ds[cs][convert(tape[ptr])];
  920.        move_a = da[cs][convert(tape[ptr])];  
  921.        ptape[ptr]=' ';
  922.        if (isvalid(move_s,move_a)){
  923.            // update machine to reflect new move
  924.            cs = move_s;
  925.            action = uppercase(move_a);
  926.            stepa.play();
  927.            switch(action) {
  928.                case '>': 
  929.                      rot++;
  930.                      shift = -5;
  931.                      paint(g);
  932.                      rot++;
  933.                      ptr++;
  934.                      shift = 0;
  935.                      break;
  936.                case '<':
  937.                      rot--;
  938.                      shift = 5;
  939.                      paint(g);
  940.                      rot--;
  941.                      ptr--;
  942.                      shift = 0;
  943.                      break;
  944.                default:{  
  945.                      tape[ptr] = action;
  946.                }
  947.            }
  948.        }
  949.        else{
  950.            done = true; 
  951.            auto_pressed = false;
  952.        }
  953.   }
  954.  }
  955.  compute_pressed = false;
  956.   paint(g); 
  957. }
  958. }
  959.  
  960. public void computethis()
  961. // compute new move
  962. {
  963.    if (running && compute_pressed){
  964.        int ts = convert(tape[ptr]);
  965.        if (ts != -999){
  966.        move_s = ds[cs][convert(tape[ptr])];
  967.        move_a = da[cs][convert(tape[ptr])];  
  968.        ptape[ptr]=' ';
  969.        if (isvalid(move_s,move_a)){
  970.            cs = move_s;
  971.            action = uppercase(move_a);
  972.            switch(action) {
  973.                case '>': ptr++;
  974.                      rot++;
  975.                      break;
  976.                case '<': ptr--;
  977.                      rot--;
  978.                      break;
  979.                default:{  
  980.                      tape[ptr] = action;
  981.                }
  982.            }
  983.        }
  984.        else
  985.            done = true; 
  986.   }
  987.  }
  988.    repaint();
  989. }
  990. }
  991.  
  992.